/*
 * Copyright (c) 2009-2013 EvTech Project
 * All rights reserved.
 * 
 * This file is part of LModeller.
 *
 * LModeller is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or 
 * (at your option) any later version.
 *
 * LModeller is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with LModeller.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package fi.honkalampisaatio.lmodeller.ui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.Iterator;

import org.lwjgl.util.Rectangle;

import fi.honkalampisaatio.lmodeller.LanguageResource;
import fi.honkalampisaatio.lmodeller.LModeller;
import fi.honkalampisaatio.lmodeller.Logger;
import fi.honkalampisaatio.lmodeller.ModelViewPage;
import fi.honkalampisaatio.lmodeller.blocks.*;
import fi.honkalampisaatio.lmodeller.selection.ModelSelectionEvent;
import fi.honkalampisaatio.lmodeller.ui.Model3DView.VIEWMODES;
import glapp.GLApp;

public class ModelMenu extends GameView implements ActionListener {

	public static final String MODELS_FOLDER = "./mallit/";
	ArrayList<Model3DView> modelButtons = new ArrayList<Model3DView>();
	ArrayList<GameTextLabel> modelLabels = new ArrayList<GameTextLabel>();
	ArrayList<BlockModel> models = new ArrayList<BlockModel>();


	public ModelMenu() {
		super(EnumSet.of(BUTTONFLAGS.BACK, BUTTONFLAGS.HOME, BUTTONFLAGS.UPLABEL, 
				BUTTONFLAGS.VOICE, BUTTONFLAGS.PREVIOUS, BUTTONFLAGS.NEXT));
	}
	
    public void init()
    {
    	int h = GLApp.getHeight()/10;
    	int w = GLApp.getWidth()/10;
    	for(int y=0; y<3; y++)
    	{
    		for(int x = 0; x<4; x++)
    		{
    			Model3DView button = new Model3DView(
    					new Rectangle((int)(w*(x*2.05f+1)),
    							(int) (GLApp.getHeight() - (h*(y*2.7f+3.5f))),
    							(int)(w*1.8),h*2));
    			button.setup();
    			button.setViewMode(VIEWMODES.FRONT);
    			button.setShowBlockCount(true, LModeller.actionColor);
    			modelButtons.add(button);
    			GameTextLabel modelLabel = new GameTextLabel(new Rectangle((int)(w*(x*2.05f+1)),
    					(int) (GLApp.getHeight() - (h*(y*2.7f+1.5f))),
						(int)(w*1.8),(int)(h*0.5)), 
						(int)(h*0.4), LModeller.actionColor);
    			modelLabels.add(modelLabel);
            	super.addComponent(modelLabel);
            	super.addComponent(button);
            	button.addActionListener(this);
    		}
    	}
    	
    	//read model files from directory
		File folder = new File(MODELS_FOLDER);
		if (folder.exists()) {
			ArrayList<BlockModel> hardModels = new ArrayList<BlockModel>();
		    File[] listOfFiles = folder.listFiles();
		    for (int i = 0; i < listOfFiles.length; i++) {
			      if (listOfFiles[i].isFile()) {
			    	  String filename = listOfFiles[i].getName();
			    	  String ext = filename.substring(filename.lastIndexOf('.')+1,filename.length());
			    	if (ext.equalsIgnoreCase("ldr") ) {  
				        BlockModel model = BlockBuilder.CreateModel(listOfFiles[i]);
				        if(model!=null && checkBlocks(model))
				        {
				        	// sorting list by a count of blocks and a difficulty level
				        	int blockCount = model.getBlocks().size();
				        	//if 3D-model
				        	if(model.getSize().getZ()>40)
				        	{
					        	int targetIndex = hardModels.size();
					        	for(int modelIndex = 0; modelIndex<hardModels.size(); modelIndex++)
					        	{
					        		if(hardModels.get(modelIndex).getBlocks().size()>blockCount)
					        		{
					        			targetIndex = modelIndex;
					        			break;
					        		}
					        	}
					        	hardModels.add(targetIndex, model);
				        	}
				        	else //only 2D
				        	{
					        	int targetIndex = models.size();
					        	for(int modelIndex = 0; modelIndex<models.size(); modelIndex++)
					        	{
					        		if(models.get(modelIndex).getBlocks().size()>blockCount)
					        		{
					        			targetIndex = modelIndex;
					        			break;
					        		}
					        	}
					        	models.add(targetIndex, model);
				        	}
				        }
				        else
				        {
					        System.err.println("The model " + filename + " abandonded");
				        }
			      	}
			      }
			}
		    //Add 3D-models in end of the list
		    for(int hardIndex = 0; hardIndex < hardModels.size(); hardIndex++)
		    {
	        	models.add(hardModels.get(hardIndex));
		    }
		}

    	setUpLabelText(LanguageResource.getInstance().get("CHOOSE_MODEL"));
		setUpToolTipSentence(LanguageResource.getInstance().get("CHOOSE_MODEL"));
    	setInstructionSentence(LanguageResource.getInstance().get("CHOOSE_MODEL"));

    	setPageCount((int)Math.ceil(models.size() / (double)modelButtons.size()));
    	setPage();
    }
    
    
	private boolean checkBlocks(BlockModel model) {
		boolean retVal = true;
		ArrayList<Block> blocks = BlockBox.getBlockBox().getCopyofAllBlocks();
		Iterator<Block> modelBlocks = model.getBlocks().iterator();
		while(modelBlocks.hasNext())
		{
			Block modelBlock = modelBlocks.next();
			Iterator<Block> allBlocks = blocks.iterator();
			boolean isFound = false;
			while(allBlocks.hasNext() && !isFound)
			{
				Block blockFromAll = allBlocks.next();
				if(blockFromAll.compare(modelBlock))
				{
					isFound = true;
					allBlocks.remove();
					break;
				}
				
			}
			if(!isFound)
			{
				retVal = false;
				break;
			}
		}
		return retVal;
	}

	protected void setPage()
	{
		for(int i=0; i<modelButtons.size(); i++)
		{
			int modelIndex = getCurrentPage()*modelButtons.size()+i;
			if(modelIndex<models.size())
			{
				modelButtons.get(i).setModel(models.get(modelIndex), true);
				if(modelLabels!=null && i<modelLabels.size() && modelLabels.get(i)!=null)
				{
					modelLabels.get(i).setText(models.get(modelIndex).getName());
				}
			}
			else
			{
				modelButtons.get(i).setModel(null, true);
				if(modelLabels!=null && modelLabels.size()>i && modelLabels.get(i)!=null)
				{
					modelLabels.get(i).setText(null);
				}
			}
		}
	}

	@Override
	protected void refreshPage(int page) {
		if(models.size()>modelButtons.size()*(page))
		{
			Logger.getInstance().log("Model Menu: page "+ page +" selected");
	    	setPage();
		}
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if(e.getSource() !=null && e.getSource() instanceof Model3DView)
		{
			Model3DView button = (Model3DView)e.getSource();
			if(button.getModel()!=null)
			{
				ArrayList<ModelViewPage> pages = new ArrayList<ModelViewPage>();

				BlockModel model = button.getModel();
				pages.add(new ModelViewPage(model, LanguageResource.getInstance().get("LOOK")));
				for(int r=0;r<model.getBlocks().size();r++)
				{
					BlockModel subModel = new BlockModel();
					subModel.setName(model.getName());
					for(int idx = 0; idx<=r; idx++)
					{
						subModel.addBlock(model.getBlocks().get(idx));
					}
					subModel.processModel();
					pages.add(new ModelViewPage(subModel, LanguageResource.getInstance().get("BUILD") + " " + (r+1) + "/" 
							+ model.getBlocks().size(), LanguageResource.getInstance().get("BUILD")));
				}
				pages.add(new ModelViewPage(model, LanguageResource.getInstance().get("READY")));
				
				ModelSelectionEvent se = new ModelSelectionEvent(this, pages);
				Logger.getInstance().log("Model Menu: Model " + model.getName() + " selected");
				this.fireSelectionEvent(se);
			}
		}
	}
}
